import { routeMap, encodeKey } from "./store.js";
class Router {
  /**
   * 初始化方法
   * @param {object} opt
   */
  init(opt = {}) {
    const { routes } = opt;
    if (routes) {
      Object.keys(routes).map((key) => {
        const route = routes[key];
        routeMap[key] = route;
        if (route.path) {
          routeMap[route.path] = route;
        }
        return key;
      });
    }
  }

  /**
   * 跳转页面
   * @param {object} routeObj { name, data, query, type}
   */
  forward(routeObj = {}, isReplace = false) {
    const { name, data, query, type } = routeObj;
    let url = "";
    const queryData = query || {};
    if (!name) {
      throw new Error("路由名称不能为空");
    }
    const route = this.parser(name);
    if (!route) {
      throw new Error("没有匹配的路由规则");
    }
    if (type === "tab") {
      route.type = "tab";
    }
    url = route.path;
    if (data) {
      queryData[encodeKey] = this.encode(data);
    }
    if (route.type !== "tab") {
      url += `?${this.querify(queryData)}`;
    }
    const opt = { url };
    if (!url) {
      throw new Error("路由url不能为空");
    }
    if (route.type === "tab" || type === "tab") {
      isReplace = false;
    }
    if (isReplace) {
      return uni.redirectTo(opt);
    }
    switch (route.type) {
      case "tab":
        return uni.switchTab(opt);
      default:
        return uni.navigateTo(opt);
    }
  }

  /**
   * 返回
   * @param {object} option { delta }
   */
  pop(option) {
    return uni.navigateBack(option);
  }

  /**
   * 关闭所有页面，打开到应用内的某个页面
   * @param {object} routeObj { name, data, query}
   */
  relaunch(routeObj = {}) {
    const { name, data, query } = routeObj;
    let url = "";
    const queryData = query || {};
    if (!name) {
      throw new Error("路由名称不能为空");
    }
    const route = this.parser(name);
    if (!route) {
      throw new Error("没有匹配的路由规则");
    }
    url = route.path;
    if (data) {
      queryData[encodeKey] = this.encode(data);
    }
    if (route.type !== "tab") {
      url += `?${this.querify(queryData)}`;
    }
    if (!url) {
      throw new Error("路由url不能为空");
    }
    return uni.reLaunch({
      url,
    });
  }

  /**
   * 前进
   * @param {object} option
   */
  async push(option) {
    const [error, res] = await this.forward(option);
    if (error === null) {
      return res;
    } else {
      throw error;
    }
  }

  /**
   * 替换
   * @param {object} option
   */
  async replace(option) {
    const [error, res] = await this.forward(option, true);
    if (error === null) {
      return res;
    } else {
      throw error;
    }
  }

  /**
   * 编码
   * @param {object} data
   */
  encode(data) {
    let encodeData;
    // #ifdef H5
    encodeData = encodeURIComponent(
      JSON.stringify(data)
        .replace(/%/g, "%25")
        .replace(/#/g, "%23")
        .replace(/&/g, "%26")
        .replace(/=/g, "%3D")
    );
    // #endif
    // #ifndef H5
    encodeData = encodeURIComponent(JSON.stringify(data));
    // #endif
    return encodeData;
  }

  /**
   * query化
   * @param {object} obj
   */
  querify(obj) {
    return Object.keys(obj)
      .map((k) => {
        const v = obj[k];
        return `${k}=${v}`;
      })
      .join("&");
  }

  /**
   * 路由名称转路径
   * @param {string} name 路由名
   */
  name2path(name) {
    return name.replace(/\./g, "/");
  }

  /**
   * 路由解析
   * @param {string} name 路由名
   */
  parser(name) {
    if (!name) {
      throw new Error("路由名字不能为空");
    }
    let route = routeMap[name];
    const path = this.name2path(name);
    const pathArr = path.split("/");
    const lastPath = pathArr[pathArr.length - 1];
    const realPath = `${path}/${lastPath}`;
    if (!route) {
      const path = `/pages/${realPath}`;
      route = routeMap[path] || {
        type: "page",
        path,
      };
    }
    return route;
  }
}

const router = new Router();

export { router };

export default Router;
